﻿#pragma once

#define REFLECT_PP_FOREACH_1(f, _1) f(_1)
#define REFLECT_PP_FOREACH_2(f, _1, _2) f(_1) f(_2)
#define REFLECT_PP_FOREACH_3(f, _1, _2, _3) f(_1) f(_2) f(_3)
#define REFLECT_PP_FOREACH_4(f, _1, _2, _3, _4) f(_1) f(_2) f(_3) f(_4)
#define REFLECT_PP_FOREACH_5(f, _1, _2, _3, _4, _5) f(_1) f(_2) f(_3) f(_4) f(_5)
#define REFLECT_PP_FOREACH_6(f, _1, _2, _3, _4, _5, _6) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6)
#define REFLECT_PP_FOREACH_7(f, _1, _2, _3, _4, _5, _6, _7) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7)
#define REFLECT_PP_FOREACH_8(f, _1, _2, _3, _4, _5, _6, _7, _8) f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8)
#define REFLECT_PP_FOREACH_9(f, _1, _2, _3, _4, _5, _6, _7, _8, _9)                                                    \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9)
#define REFLECT_PP_FOREACH_10(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10)                                              \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10)
#define REFLECT_PP_FOREACH_11(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11)                                         \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11)
#define REFLECT_PP_FOREACH_12(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12)                                    \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12)
#define REFLECT_PP_FOREACH_13(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13)                               \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13)
#define REFLECT_PP_FOREACH_14(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14)                          \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14)
#define REFLECT_PP_FOREACH_15(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15)                     \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15)
#define REFLECT_PP_FOREACH_16(f, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16)                \
    f(_1) f(_2) f(_3) f(_4) f(_5) f(_6) f(_7) f(_8) f(_9) f(_10) f(_11) f(_12) f(_13) f(_14) f(_15) f(_16)

// 注意添加 /Zc:preprocessor 编译选项，否则 REFLECT_PP_NARGS 不能正确计算参数数量
#define REFLECT_PP_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
#define REFLECT_PP_NARGS(...) REFLECT_PP_NARGS_IMPL(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

// 多层嵌套展开求值
#define REFLECT_EXPAND_IMPL(...) __VA_ARGS__
#define REFLECT_EXPAND(...) REFLECT_EXPAND_IMPL(__VA_ARGS__)
#define REFLECT_CONCAT_IMPL(a, b) a##b
#define REFLECT_CONCAT(a, b) REFLECT_CONCAT_IMPL(a, b)

namespace xy
{

namespace utils
{

namespace details
{

enum class member_type
{
    member_variable,
    static_variable,
    member_function,
    static_function
};

// T 是成员变量的类型，C 是类类型，Ts 是参数类型
template <class T> struct get_member_type
{
    using class_type = void;
    using member_type = void;
    using return_type = void;
    using args_type = void;
};

template <class T, class C> struct get_member_type<T C::*>
{
    using class_type = C;
    using variable_type = T;
    static constexpr member_type type = member_type::member_variable;
};

template <class T> struct get_member_type<T *>
{
    using variable_type = T;
    static constexpr member_type type = member_type::static_variable;
};

#define FUNCTION_TYPE(Type)                                                                                            \
    template <class T, class C, class... Ts> struct get_member_type<Type>                                              \
    {                                                                                                                  \
        using class_type = C;                                                                                          \
        using return_type = T;                                                                                         \
        using args_type = std::tuple<Ts...>;                                                                           \
        static constexpr member_type type = member_type::member_function;                                              \
    };

FUNCTION_TYPE(T (C::*)(Ts...))
FUNCTION_TYPE(T (C::*)(Ts...) const)
FUNCTION_TYPE(T (C::*)(Ts...) &)
FUNCTION_TYPE(T (C::*)(Ts...) const &)
FUNCTION_TYPE(T (C::*)(Ts...) &&)
FUNCTION_TYPE(T (C::*)(Ts...) const &&)
FUNCTION_TYPE(T (C::*)(Ts...) noexcept)
FUNCTION_TYPE(T (C::*)(Ts...) const noexcept)
FUNCTION_TYPE(T (C::*)(Ts...) & noexcept)
FUNCTION_TYPE(T (C::*)(Ts...) const & noexcept)
FUNCTION_TYPE(T (C::*)(Ts...) && noexcept)
FUNCTION_TYPE(T (C::*)(Ts...) const && noexcept)

#undef FUNCTION_TYPE

template <class T, class... Ts> struct get_member_type<T (*)(Ts...)>
{
    using return_type = T;
    using args_type = std::tuple<Ts...>;
    static constexpr member_type type = member_type::static_function;
};

template <class T, class... Ts> struct get_member_type<T (*)(Ts...) noexcept>
{
    using return_type = T;
    using args_type = std::tuple<Ts...>;
    static constexpr member_type type = member_type::static_function;
};

template <typename T> struct reflect_trait_impl
{
    // 检测内部是否具有 for_each 方法
    static constexpr bool has_members()
    {
        return requires(T t) { t.for_each_member_ptr<T>([](const auto &, auto &&) {}); };
    }

    // 通过此结构体调用类静态方法
    template <class Func> static constexpr void for_each_member_ptr(Func &&func)
    {
        // 注意 :: 后面的是静态成员函数
        T::template for_each_member_ptr<T>(func);
    }
};

} // namespace details

// 使用此特性需要添加 /Zc:preprocessor 编译选项
struct reflect_trait
{
    /**
     * @brief 遍历类成员变量
     *
     * @tparam T
     * @tparam Func
     * @param[in] object
     * @param[in] func
     */
    template <class T, class Func> static void for_each_member_variable(const T &object, Func &&func)
    {
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name, auto &&member) {
            constexpr auto member_type = details::get_member_type<std::decay_t<decltype(member)>>::type;
            if constexpr (member_type == details::member_type::member_variable)
                func(name, object.*member);
        });
    }

    /**
     * @brief 遍历类静态变量
     *
     * @tparam T
     * @tparam Func
     * @param[in] func
     */
    template <class T, class Func> static void for_each_static_variable(Func &&func)
    {
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name, auto &&member) {
            constexpr auto member_type = details::get_member_type<std::decay_t<decltype(member)>>::type;
            if constexpr (member_type == details::member_type::static_variable)
                func(name, *member);
        });
    }

    /**
     * @brief 获得类成员变量
     *
     * @tparam T
     * @tparam Ty
     * @param[in] object
     * @param[in] name
     * @param[in] member
     * @return 是否找到了对应的成员变量
     */
    template <class T, class Ty> static bool member_variable(const T &object, const std::string &name, Ty &member)
    {
        bool applied = false;
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name_, auto &&member_) {
            using Tz = std::decay_t<decltype(member_)>;
            constexpr auto member_type = details::get_member_type<Tz>::type;
            if constexpr (member_type == details::member_type::member_variable)
            {
                using Tu = details::get_member_type<Tz>::variable_type;
                if constexpr (std::is_same_v<Ty, Tu> || std::is_same_v<const Ty, Tu>)
                {
                    if (name == name_)
                    {
                        member = object.*member_;
                        applied = true;
                    }
                }
            }
        });
        return applied;
    }

    /**
     * @brief 设置类成员变量
     *
     * @tparam T
     * @tparam Ty
     * @param[in] object
     * @param[in] name
     * @param[in] member
     * @return 是否找到了对应的成员变量
     */
    template <class T, class Ty> static bool set_member_variable(T &object, const std::string &name, const Ty &member)
    {
        bool applied = false;
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name_, auto &&member_) {
            using Tz = std::decay_t<decltype(member_)>;
            constexpr auto member_type = details::get_member_type<Tz>::type;
            if constexpr (member_type == details::member_type::member_variable)
            {
                if constexpr (std::is_same_v<Ty, details::get_member_type<Tz>::variable_type>)
                {
                    if (name == name_)
                    {
                        object.*member_ = member;
                        applied = true;
                    }
                }
            }
        });
        return applied;
    }

    /**
     * @brief 获得类静态变量
     *
     * @tparam T
     * @tparam Ty
     * @param[in] name
     * @param[in] member
     * @return 是否找到了对应的静态变量
     */
    template <class T, class Ty> static bool static_variable(const std::string &name, Ty &member)
    {
        bool applied = false;
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name_, auto &&member_) {
            using Tz = std::decay_t<decltype(member_)>;
            constexpr auto member_type = details::get_member_type<Tz>::type;
            if constexpr (member_type == details::member_type::static_variable)
            {
                if constexpr (std::is_same_v<Ty *, Tz> || std::is_same_v<const Ty *, Tz>)
                {
                    if (name == name_)
                    {
                        member = *member_;
                        applied = true;
                    }
                }
            }
        });
        return applied;
    }

    /**
     * @brief 设置类静态变量
     *
     * @tparam T
     * @tparam Ty
     * @param[in] object
     * @param[in] name
     * @param[in] member
     * @return 是否找到了对应的静态变量
     */
    template <class T, class Ty> static bool set_static_variable(const std::string &name, const Ty &member)
    {
        bool applied = false;
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name_, auto &&member_) {
            using Tz = std::decay_t<decltype(member_)>;
            constexpr auto member_type = details::get_member_type<Tz>::type;
            if constexpr (member_type == details::member_type::static_variable)
            {
                if constexpr (std::is_same_v<Ty *, Tz>)
                {
                    if (name == name_)
                    {
                        *member_ = member;
                        applied = true;
                    }
                }
            }
        });
        return applied;
    }

    /**
     * @brief 调用类成员函数，仅支持 void 返回
     *
     * @tparam T
     * @tparam Args
     * @param[in] cobject
     * @param[in] name
     * @param[in] args
     * @return true
     * @return false
     */
    template <class T, typename... Args>
    static bool member_function(const T &object, const std::string &name, Args... args)
    {
        bool applied = false;
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name_, auto &&member_) {
            using Tz = std::decay_t<decltype(member_)>;
            constexpr auto member_type = details::get_member_type<Tz>::type;
            if constexpr (member_type == details::member_type::member_function)
            {
                if constexpr (std::is_same_v<std::tuple<Args...>, typename details::get_member_type<Tz>::args_type>)
                {
                    if (name == name_)
                    {
                        (object.*member_)(std::forward<Args>(args)...);
                        applied = true;
                    }
                }
            }
        });
        return applied;
    }

    /**
     * @brief 调用类静态方法，仅支持 void 返回
     *
     * @tparam T
     * @tparam Args
     * @param[in] name
     * @param[in] args
     * @return true
     * @return false
     */
    template <class T, typename... Args> static bool static_function(const std::string &name, Args... args)
    {
        bool applied = false;
        details::reflect_trait_impl<std::decay_t<T>>::for_each_member_ptr([&](const auto &name_, auto &&member_) {
            using Tz = std::decay_t<decltype(member_)>;
            constexpr auto member_type = details::get_member_type<Tz>::type;
            if constexpr (member_type == details::member_type::static_function)
            {
                if constexpr (std::is_same_v<std::tuple<Args...>, typename details::get_member_type<Tz>::args_type>)
                {
                    if (name == name_)
                    {
                        member_(std::forward<Args>(args)...);
                        applied = true;
                    }
                }
            }
        });
        return applied;
    }
};

} // namespace utils

} // namespace xy

// 遍历展开 f(...)
#define REFLECT_PP_FOR_EACH(f, ...)                                                                                    \
    REFLECT_EXPAND(REFLECT_CONCAT(REFLECT_PP_FOREACH_, REFLECT_PP_NARGS(__VA_ARGS__))(f, __VA_ARGS__))

// 绑定变量名和变量指针
#define REFLECT_MEMBER_PTR(x) func(#x, &This::x);

// 类内部反射宏
#define REFLECT(...)                                                                                                   \
    template <class This, class Func> static constexpr void for_each_member_ptr(Func &&func)                           \
    {                                                                                                                  \
        REFLECT_PP_FOR_EACH(REFLECT_MEMBER_PTR, __VA_ARGS__)                                                           \
    }